package com.nightpiter.view.drawer.dynamic;

import java.util.ArrayList;

import com.nightpiter.view.graphics.Canvas;

/**
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 * 
 */
class BacillusUltimate {

	@SuppressWarnings("unused")
	private AmoebaUltimate evenAmoebaUltimate, oddAmoebaUltimate;

	/** the Bacillus to call the draw method */
	private Bacillus rootBacillus;

	/** array of primitive Bacilli that make up this Bacillus */
	private ArrayList<PrimitiveBacillus> primitiveBacilli = new ArrayList<PrimitiveBacillus>();

	/**
	 * @param evenAmoebaUltimate
	 * @param oddAmoebaUltimate
	 */
	public BacillusUltimate(AmoebaUltimate evenAmoebaUltimate,
			AmoebaUltimate oddAmoebaUltimate) {
		this.evenAmoebaUltimate = evenAmoebaUltimate;
		this.oddAmoebaUltimate = oddAmoebaUltimate;
		evenAmoebaUltimate.addNeighbor(oddAmoebaUltimate, this);
		oddAmoebaUltimate.addNeighbor(evenAmoebaUltimate, this);
	}

	public void build() {
		ArrayList<Bacillus> bacilli = new ArrayList<Bacillus>(primitiveBacilli);

		while (bacilli.size() > 1
				|| bacilli.get(0).evenAmoeba.intermediateAmoeba != null
				|| bacilli.get(0).oddAmoeba.intermediateAmoeba != null) {
			Bacillus bacillus = null;
			Amoeba masterAmoeba = null;
			Amoeba slaveAmoeba = null;
			IntermediateAmoeba minIntermediateAmoeba = null, intermediateAmoeba;
			for (Bacillus eachBacillus : bacilli) {
				if (eachBacillus.evenAmoeba.intermediateAmoeba != null) {
					intermediateAmoeba = eachBacillus.evenAmoeba.intermediateAmoeba;
					if (minIntermediateAmoeba == null
							|| minIntermediateAmoeba
									.compareTo(intermediateAmoeba) > 0) {
						minIntermediateAmoeba = intermediateAmoeba;
						bacillus = eachBacillus;
						masterAmoeba = bacillus.evenAmoeba;
						slaveAmoeba = bacillus.oddAmoeba;
					}
				}
				if (eachBacillus.oddAmoeba.intermediateAmoeba != null) {
					intermediateAmoeba = eachBacillus.oddAmoeba.intermediateAmoeba;
					if (minIntermediateAmoeba == null
							|| minIntermediateAmoeba
									.compareTo(intermediateAmoeba) > 0) {
						minIntermediateAmoeba = intermediateAmoeba;
						bacillus = eachBacillus;
						masterAmoeba = bacillus.oddAmoeba;
						slaveAmoeba = bacillus.evenAmoeba;
					}
				}
			}
			assert bacillus != null;
			assert masterAmoeba != null && slaveAmoeba != null;

			IntermediateBacillus intermediateBacillus;
			assert (masterAmoeba.brotherAmoeba != null);

			Bacillus brotherBacillus = masterAmoeba.brotherAmoeba
					.getBacillus(slaveAmoeba);

			// TODO I am not sure if the method invoked above performs exactly
			// the same as we expect. May be we should use the cycle below.

			// Bacillus brotherBacillus = null;
			// for (Bacillus bacillus2 : bacilli) {
			// if (bacillus2.evenAmoeba == masterAmoeba.brotherAmoeba
			// && bacillus2.oddAmoeba == slaveAmoeba) {
			// brotherBacillus = bacillus2;
			// break;
			// }
			// if (bacillus2.oddAmoeba == masterAmoeba.brotherAmoeba
			// && bacillus2.evenAmoeba == slaveAmoeba) {
			// brotherBacillus = bacillus2;
			// break;
			// }
			// }
			if (brotherBacillus != null) {
				intermediateBacillus = new IntermediateBacillus(
						masterAmoeba.intermediateAmoeba, slaveAmoeba, bacillus,
						brotherBacillus);
				bacilli.remove(brotherBacillus);
			} else {
				intermediateBacillus = new IntermediateBacillus(
						masterAmoeba.intermediateAmoeba, slaveAmoeba, bacillus);
			}

			bacilli.remove(bacillus);
			bacilli.add(intermediateBacillus);

		}

		rootBacillus = bacilli.get(0);
		assert rootBacillus.intermediateBacillus == null;
	}

	public void addPrimitiveBacillus(PrimitiveBacillus primitiveBacillus) {
		primitiveBacilli.add(primitiveBacillus);
	}

	public void draw(Canvas canvas) {
		rootBacillus.draw(canvas);
	}
	
}
